package com.hzw.saas.web.app.old.storage.controller;

import java.util.List;
import java.util.Objects;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.hzw.saas.api.old.storage.IResourceShareService;
import com.hzw.saas.api.old.storage.bo.ResourceShareBO;
import com.hzw.saas.api.old.storage.bo.ResourceSharePreviewBO;
import com.hzw.saas.api.old.storage.enums.ResourceAuthEnum;
import com.hzw.saas.api.property.IPropertyService;
import com.hzw.saas.api.property.enmus.SysParamKeyEnum;
import com.hzw.saas.api.storage.bo.ResourceShareTokenBO;
import com.hzw.saas.api.storage.constants.StorageConsts;
import com.hzw.saas.api.user.bo.UserBaseInfoBO;
import com.hzw.saas.common.config.annotation.SysLog;
import com.hzw.saas.common.security.pojo.dto.SaasUser;
import com.hzw.saas.common.security.utils.SecurityUtils;
import com.hzw.saas.common.util.LangUtil;
import com.hzw.saas.common.util.PathUtils;
import com.hzw.saas.common.util.constants.PathConsts;
import com.hzw.saas.service.old.storage.annotation.FileAuthBefore;
import com.hzw.saas.service.old.storage.annotation.FolderAuthBefore;
import com.hzw.saas.web.app.old.storage.dto.ResourceShareDTO;
import com.hzw.saas.web.app.old.storage.param.ResourceShareDeleteParam;
import com.hzw.saas.web.app.old.storage.param.ResourceSharePostParam;
import com.hzw.saas.web.app.old.storage.param.ResourceSharePwdParam;
import com.hzw.saas.web.app.old.storage.param.ResourceShareSaveParam;
import cn.hutool.core.util.StrUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;


/**
 * @author zzl
 * @since 07/04/2021
 */
// @Controller
// @Validated
@RequiredArgsConstructor
@Slf4j
// @Api(tags = "资源管理/资源分享")
public class UserResourceShareController {

    private static final String ACCESS_TOKEN_KEY = "share-access-token";

    private final HttpServletRequest request;
    private final IResourceShareService shareService;

    @Resource(name = IPropertyService.SYS_PARAM_BEAN)
    private final IPropertyService<SysParamKeyEnum> propertyService;

    private String shareLinkPrefix = "";

    @PostConstruct
    public void init() {
        String webHost = propertyService.getPropertyValue(SysParamKeyEnum.APP_FRONTEND_HOST, "");
        shareLinkPrefix = PathUtils.connectUri(webHost, StorageConsts.SHARE_LINK_PREFIX).concat(PathConsts.SLASH);
    }

    @GetMapping("/resource/share/preview/{shareId}/user_info")
    @SysLog
    @ApiOperation(value = "获取分享者信息", notes = "获取分享者的基本信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "shareId", value = "分享ID", dataType = "String", paramType = "path", required = true),
    })
    @ApiOperationSort(11)
    public ResponseEntity<UserBaseInfoBO> getUserInfo(@PathVariable String shareId) {
        UserBaseInfoBO sharedUserInfo = shareService.getUserInfo(shareId);
        return ResponseEntity.ok(sharedUserInfo);
    }

    @GetMapping(StorageConsts.SHARE_LINK_PREFIX + "{shareId}")
    @SysLog
    @ApiOperation(value = "查看分享", notes = "查看分享的资源列表，若链接已加密，会返回403错误，此时请求<获取加密分享token>获取token，后调用此接口，同时设置请求头share-access-token")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "shareId", value = "分享ID", dataType = "String", paramType = "path", required = true),
        @ApiImplicitParam(name = "supIdPath", value = "分享目录路径(目录ID路径模式)", dataType = "String", paramType = "query")
    })
    @ApiResponses({
        @ApiResponse(code = 200, message = "返回分享的资源"),
        @ApiResponse(code = 403, message = "未授权，请调用'获取加密链接token'接口"),
        @ApiResponse(code = 404, message = "资源已过期或被删除")
    })
    @ApiOperationSort(12)
    public ResponseEntity<ResourceSharePreviewBO> checkSharedLink(@PathVariable String shareId, String supIdPath) {
        String accessToken = request.getHeader(ACCESS_TOKEN_KEY);
        shareService.assertValidToken(shareId, accessToken);
        ResourceSharePreviewBO sharedResources = shareService.listSharedResources(shareId, supIdPath);
        return ResponseEntity.ok(sharedResources);
    }

    @PostMapping("/resource/share/preview/auth")
    @SysLog(operation = "获取加密分享token", mode = 3)
    @ApiOperation(value = "获取加密分享token", notes = "获取加密分享token，获取后，访问<查看分享>接口, 并设置请求头share-access-token")
    @ApiResponses({
        @ApiResponse(code = 200, message = "请求成功"),
        @ApiResponse(code = 400, message = "密码错误"),
        @ApiResponse(code = 404, message = "资源已过期或被删除")
    })
    @ApiOperationSort(13)
    public ResponseEntity<ResourceShareTokenBO> getCheckAuth(@Validated @RequestBody ResourceSharePwdParam param) {
        ResourceShareTokenBO token = shareService.checkSharePwd(param.getShareId(), param.getPassword());
        return ResponseEntity.ok(token);
    }

    @PostMapping("/resource/share/copy")
    @FolderAuthBefore(folderId = "#param.tarSupId", auth = ResourceAuthEnum.OWN)
    @SysLog(operation = "保存分享", mode = 3)
    @ApiOperation(value = "保存分享", notes = "保存分享的资源到个人存储空间，若链接已加密，会返回403错误，此时请设置请求头share-access-token")
    @ApiResponses({
        @ApiResponse(code = 200, message = "操作成功"),
        @ApiResponse(code = 400, message = "请求参数错误"),
        @ApiResponse(code = 403, message = "无访问权限"),
        @ApiResponse(code = 413, message = "存储空间不足")
    })
    @ApiOperationSort(14)
    public ResponseEntity<Void> saveSharedResources(@Validated @RequestBody ResourceShareSaveParam param) {
        String accessToken = request.getHeader(ACCESS_TOKEN_KEY);
        shareService.assertValidToken(param.getShareId(), accessToken);
        shareService.saveSharedResources(param.getShareId(), param.getTarSupId(), param.getFolderIdPaths(), param.getFileIdPaths());
        return ResponseEntity.ok().build();
    }

    @PostMapping("/resource/share")
    @FileAuthBefore(fileIds = "#param.fileIds", auth = ResourceAuthEnum.OWN)
    @FolderAuthBefore(folderIds = "#param.folderIds", auth = ResourceAuthEnum.OWN)
    @SysLog(operation = "创建分享", mode = 3)
    @ApiOperation(value = "创建分享", notes = "创建分享")
    @ApiOperationSort(15)
    public ResponseEntity<ResourceShareDTO> createShareLink(@Validated @RequestBody ResourceSharePostParam param) {
        SaasUser user = SecurityUtils.getUser();
        if (Objects.nonNull(param.getEnablePassword()) && param.getEnablePassword() > 0 && StrUtil.isBlank(param.getPassword())) {
            param.setPassword(LangUtil.getRandom("", 4));
        }
        String shareId = shareService.share(user.getUserId(), param.getShareName(),
            param.getFolderIds(), param.getFileIds(), param.getPassword(), param.getExpireTime());
        ResourceShareDTO result = new ResourceShareDTO()
            .setShareId(shareId)
            .setPassword(param.getPassword())
            .setShareLink(shareLinkPrefix.concat(shareId));
        return ResponseEntity.ok(result);
    }

    @GetMapping("/resource/shares")
    @SysLog
    @ApiOperation(value = "查看已创建的分享", notes = "查看用户自己已创建的分享")
    @ApiOperationSort(16)
    public ResponseEntity<List<ResourceShareBO>> listShare() {
        SaasUser user = SecurityUtils.getUser();
        List<ResourceShareBO> resourceShareBOS = shareService.listShare(user.getUserId());
        for (ResourceShareBO resourceShareBO : resourceShareBOS) {
            resourceShareBO.setShareLink(shareLinkPrefix.concat(resourceShareBO.getPid()));
        }
        return ResponseEntity.ok(resourceShareBOS);
    }

    @DeleteMapping("/resource/shares")
    @SysLog(operation = "删除分享", mode = 3)
    @ApiOperation(value = "删除分享", notes = "删除分享，支持批量")
    @ApiOperationSort(17)
    public ResponseEntity<Void> deleteShares(@Validated @RequestBody ResourceShareDeleteParam param) {
        String userId = SecurityUtils.getUser().getUserId();
        shareService.assertAuthOwn(userId, param.getShareIds());
        shareService.deleteShare(param.getShareIds());
        return ResponseEntity.ok().build();
    }

}
